package com.system.demo.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.system.demo.commonService.RabbitMQService;
import com.system.demo.entity.DTO.PaperSearchDTO;
import com.system.demo.entity.DTO.PaperSubmitApplicationDTO;
import com.system.demo.entity.database.Paper;
import com.system.demo.entity.database.Student;
import com.system.demo.entity.database.UserNotifications;
import com.system.demo.entity.excelFile.PaperDTOForExcel;
import com.system.demo.mapper.PaperSubmitMapper;
import com.system.demo.mapper.StudentMapper;
import com.system.demo.service.PaperService;
import com.system.demo.tool.ResponseResult;
import com.system.demo.utils.ExcelExportUtil;
import com.system.demo.utils.MinioUtils;
import com.system.demo.utils.PaperDTOMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import static com.system.demo.service.constant.ApplicationStatus.*;
import static com.system.demo.service.constant.PaperConstant.MINIO_PAPER_EVIDENCE_PATH;
import static com.system.demo.service.constant.UserNotificationConstant.NO_CHECK;


@Service
public class PaperServiceImpl implements PaperService {
    @Autowired
    private PaperSubmitMapper paperSubmitMapper;

    @Autowired
    private MinioUtils minioUtils;

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private RabbitMQService rabbitMQService;

    @Value("${myIp.ip}")
    private String ip;

    @Value("${minio.port}")
    private int port;

    @Value("${minio.bucketName}")
    private String bucketName;


    /**
     * 论文软著专利申报审核：
     *
     * @param paperSubmitApplicationDTO 前端提交的论文申请表单
     * @return 返回信息
     */
    @Override
    public ResponseResult<?> PaperSumbit(PaperSubmitApplicationDTO paperSubmitApplicationDTO) {
        try{
            Paper paper = new Paper();
            paper.setUid(StpUtil.getLoginId().toString());
            paper.setTitle(paperSubmitApplicationDTO.getTitle());
            //Minio_url
            paper.setType(paperSubmitApplicationDTO.getType());
            paper.setCreateTime(LocalDateTime.now());
            paper.setParticipantMembers(paperSubmitApplicationDTO.getAuthor());
            paper.setTeamRank(paperSubmitApplicationDTO.getRank());

            //paper.setSubmitTime(LocalDateTime.now());
            paper.setStatus(SUBMITTED);

            String Uid = StpUtil.getLoginId().toString();
            System.out.println(Uid);

            paper.setPaperAbstract(paperSubmitApplicationDTO.getContent());

            LambdaQueryWrapper<Student> queryWrapper = Wrappers.lambdaQuery(Student.class)
                    .eq(Student::getUid, Uid);
            Student student = studentMapper.selectOne(queryWrapper);

            paper.setStuName(student.getStudentName());
            paper.setStuClass(student.getStudentClass());

            if(paperSubmitMapper.insert(paper)>0){

                return ResponseResult.success("论文/软著/专利提交成功");
            }
            return ResponseResult.InternalServerError("论文/软著/专利提交失败，服务器数据插入失败");

        }
        catch (Exception e){
            e.printStackTrace();
            return ResponseResult.InternalServerError("未知错误:" + e.getMessage());
        }
    }

    @Override
    public ResponseResult<?> PaperDelete(Integer id) {
        try {
            Paper application = paperSubmitMapper.findByApplicationId(id);
            String Uid = StpUtil.getLoginId().toString();
            if (!Uid.equals(application.getUid())) {
                return ResponseResult.Forbidden("你又想干嘛？");
            }
            if (application.getStatus() != SUBMITTED){
                return ResponseResult.Forbidden("已经审批完成，无法修改");
            }
            paperSubmitMapper.deleteById(id,Uid);
            return ResponseResult.success("Paper deleted successfully.");
        } catch (Exception e) {
            // 记录异常信息
            e.printStackTrace();
            return ResponseResult.InternalServerError("Failed to delete paper: " + e.getMessage());
        }
    }

    @Override
    public ResponseResult<?> LevelUpdate(Integer id, String isPass, Integer level) {
        try{
            String value =  "(" + id + ")";
            if (isPass.equals("false")) {
                LambdaQueryWrapper<Paper> queryWrapper = Wrappers.<Paper>lambdaQuery()
                        .eq(Paper::getId, id);

                int rowsUpdated = paperSubmitMapper.batchUpdateStatus(value,REJECTED_RECOGNITION_REQUEST);
                int rowsUpdated2 = paperSubmitMapper.batchUpdateCertificate(value);
                if (rowsUpdated <= 0 || rowsUpdated2 <= 0) {
                    throw new RuntimeException("批量更新失败");
                }
                return ResponseResult.success("批量更新成功");
            }
            else if(isPass.equals("true")){
                int rowsUpdated = paperSubmitMapper.batchUpdateFinalLevel(value, level.toString());
                int rowsUpdated1 = paperSubmitMapper.batchUpdateStatus(value,APPROVED_RECOGNITION_REQUEST);
                if (rowsUpdated <= 0 || rowsUpdated1 <= 0) {
                    throw new RuntimeException("批量更新失败");
                }
                return ResponseResult.success("批量更新成功");
            }
            else{
                return ResponseResult.Forbidden("你有权限吗，还是说你打错字了？");
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.BadRequest("未知错误：" + e.getMessage());
        }
    }

    @Override
    public ResponseResult<?> NoAward(Integer applicationId) {
        try{
            String Uid = StpUtil.getLoginId().toString();
            LambdaQueryWrapper<Paper> wrapper = Wrappers.lambdaQuery(Paper.class)
                    .eq(Paper::getId, applicationId);
            Paper paper = paperSubmitMapper.selectOne(wrapper);
            if (paper.getStatus() != APPROVED) {
                return ResponseResult.Forbidden("我不许你未获奖");
            }
            if(!Uid.equals(paper.getUid())){
                return ResponseResult.Forbidden("哥，别搞，我错了，这系统容不下您");
            }

            paper.setStatus(COMPLETED);
            if (paperSubmitMapper.updateById(paper)>0){
                return ResponseResult.success("更改成功");
            }
            else return ResponseResult.InternalServerError("更改失败");
        }
        catch (Exception e){
            e.printStackTrace();
            return ResponseResult.InternalServerError(e.getMessage());
        }
    }

    @Override
    public ResponseResult<?> PaperUpdate(Integer applicationId, PaperSubmitApplicationDTO paperSubmitApplicationDTO) {
        try{
            LambdaQueryWrapper<Paper> wrapper = Wrappers.lambdaQuery(Paper.class)
                    .eq(Paper::getId, applicationId);
            Paper paper = paperSubmitMapper.selectOne(wrapper);
            if (paper.getStatus() != SUBMITTED || !Objects.equals(paper.getUid(), StpUtil.getLoginId().toString())) {
                return ResponseResult.Unauthorized("无权限操作");
            }

            paper.setTitle(paperSubmitApplicationDTO.getTitle());
            paper.setType(paperSubmitApplicationDTO.getType());
            paper.setCreateTime(LocalDateTime.now());
            paper.setParticipantMembers(paperSubmitApplicationDTO.getAuthor());
            paper.setTeamRank(paperSubmitApplicationDTO.getRank());
            paper.setPaperAbstract(paperSubmitApplicationDTO.getContent());
            paper.setStatus(SUBMITTED);

            if (paperSubmitMapper.updateById(paper)>0){
                return ResponseResult.success("成功修改");
            }
            return ResponseResult.InternalServerError("修改失败");

        }
        catch (Exception e){
            e.printStackTrace();
            return ResponseResult.InternalServerError(e.getMessage());
        }
    }

    @Override
    public void downloadEvidence(List<Integer> ids, HttpServletResponse response) {
        try{
            QueryWrapper<Paper> queryWrapper = new QueryWrapper();
            queryWrapper.in("id", ids);
            List<Paper> papers = paperSubmitMapper.selectList(queryWrapper);
            List<String> FileUrls = new ArrayList<>();
            for (Paper paper : papers) {
                String name = paper.getCertificate().substring(paper.getCertificate().lastIndexOf("/") + 1);
                String Uid = paper.getUid();
                String url = Uid + "/" + MINIO_PAPER_EVIDENCE_PATH +  "/" + name;
                FileUrls.add(url);
            }
            minioUtils.ZipMultiFileToMinIO(response,bucketName,FileUrls,"证明材料");
        }
        catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * User用户查询个人论文情况
     *
     * 直接查询用户个人学号
     * @param current 页号
     * @param size 页面大小
     * @return 返回信息
     */

    @Override
    public ResponseResult<?> PaperSearch(int current,int size) {
        try{
            String userUid = StpUtil.getLoginId().toString();
            LambdaQueryWrapper<Paper> queryWrapper = new LambdaQueryWrapper<>();
            if (userUid != null) {
                queryWrapper.eq(Paper::getUid, userUid);
            }
            Page<Paper> page = new Page<>(current, size);
            Page<Paper> result = paperSubmitMapper.selectPage(page, queryWrapper);
            return ResponseResult.success("查询成功",result.getTotal(),result.getRecords());
        }
        catch (Exception e){
            e.printStackTrace();
            return ResponseResult.InternalServerError("未知错误:"+e.getMessage());
        }
    }

    /**
     * 论文软著专利查询：
     *
     * @param paperSearchDTO 前端提交的论文查询表单
     * @param current 页号
     * @param size 页面大小
     * @return 返回信息
     */
    @Override
    public ResponseResult<?> PaperSearch(PaperSearchDTO paperSearchDTO,int current,int size) {
        try{
            if (paperSearchDTO.getStuName() != null && paperSearchDTO.getStuName().isEmpty()) {
                paperSearchDTO.setStuName(null);
            }

            if (paperSearchDTO.getStartTime() != null && paperSearchDTO.getStartTime().isEmpty()){
                paperSearchDTO.setStartTime(null);
            }

            if (paperSearchDTO.getEndTime() != null && paperSearchDTO.getEndTime().isEmpty()){
                paperSearchDTO.setEndTime(null);
            }

            if (paperSearchDTO.getStuClass() != null && paperSearchDTO.getStuClass().isEmpty()) {
                paperSearchDTO.setStuClass(null);
            }

            LambdaQueryWrapper<Paper> queryWrapper = new LambdaQueryWrapper<>();

            // 按照申请状态查询
            if (paperSearchDTO.getStatus() != null) {
                queryWrapper.eq(Paper::getStatus, paperSearchDTO.getStatus());
            }

            // 按照类型查询，论文/软著/专利
            if (paperSearchDTO.getType() != null) {
                queryWrapper.eq(Paper::getType, paperSearchDTO.getType());
            }

            //
            if (paperSearchDTO.getFinalLevel() != null) {
                queryWrapper.eq(Paper::getFinalLevel, paperSearchDTO.getFinalLevel());
            }

            if (paperSearchDTO.getStuName() != null) {
                queryWrapper.like(Paper::getStuName, paperSearchDTO.getStuName());
            }

            if (paperSearchDTO.getStartTime() != null && paperSearchDTO.getEndTime() != null) {
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
                LocalDateTime startDateTime = LocalDateTime.parse(paperSearchDTO.getStartTime(), formatter);
                LocalDateTime endDateTime = LocalDateTime.parse(paperSearchDTO.getEndTime(), formatter).plusDays(1);
                if (startDateTime.isBefore(endDateTime)) {
                    queryWrapper.ge(Paper::getAwardTime, startDateTime);
                    queryWrapper.le(Paper::getAwardTime, endDateTime);
                }
            }


            if (paperSearchDTO.getStuClass() != null) {
                queryWrapper.like(Paper::getStuClass, paperSearchDTO.getStuClass());
            }

            Page<Paper> page = new Page<>(current, size);

            Page<Paper> result = paperSubmitMapper.selectPage(page, queryWrapper);

            return ResponseResult.success("筛选成功",result.getTotal(),result.getRecords());
        }
        catch (Exception e){
            e.printStackTrace();
            return ResponseResult.InternalServerError("未知错误：" + e.getMessage());
        }
    }




    /**
     * Admin进行论文审核
     *
     * @param applicationId 对应Paper表中的唯一id
     * @return 返回信息
     *
     */
    @Override
    @Transactional
    public ResponseResult<?> PaperApplicate(List<Integer> applicationId,String isPass){
        try {
            if (!isPass.equals("true") && !isPass.equals("false")) {
                return ResponseResult.Unauthorized("???????????");
            }
            // 从数据库中批量获取数据
            List<Paper> papers = paperSubmitMapper.selectBatchIds(applicationId);
            if (papers.isEmpty()) {
                return ResponseResult.NotFound("未查询到对应的记录");
            }
            for (Paper paper : papers) {
                if (paper.getStatus() != SUBMITTED){
                    return ResponseResult.Unauthorized("审批状态错误");
                }
            }
            String value =  "(" + String.join(", ", applicationId.stream().map(String::valueOf).toArray(String[]::new)) + ")";
            System.out.println(value);

            Integer newStatus = isPass.equals("true") ? APPROVED : REJECTED;

            int rowsUpdated = paperSubmitMapper.batchUpdateStatus(value, newStatus);

            if (rowsUpdated <= 0) {
                throw new RuntimeException("批量更新失败");
            }
            // 构造不同的成功或失败消息
            String messageHead = isPass.equals("true") ? "审核通过啦！" : "很遗憾";
            String messageResult = isPass.equals("true") ? "审核已通过,请尽快上传认定材料" : "审核未通过，请联系辅导员";
            for(Paper paper : papers){
                // 创建一个 UserNotifications 实体对象
                String messageBody = "您的关于《" +paper.getTitle()+"》文章申请，";
                String successMessage = messageHead + messageBody + messageResult;
                UserNotifications notification = new UserNotifications();
                notification.setUid(paper.getUid()); // 获取对应的用户 ID
                notification.setContent(successMessage);
                notification.setStatus(NO_CHECK); // 1表示已阅，0表示未读
                notification.setCreatedTime(LocalDateTime.now()); // 设置当前时间
                // 发送消息到 RabbitMQ
                rabbitMQService.sendNotification(notification);
            }
            return ResponseResult.success("批量更新成功");


        } catch (NumberFormatException e) {
            return ResponseResult.BadRequest("无效的申请ID");
        } catch (Exception e) {
            return ResponseResult.InternalServerError("审核过程中发生错误: " + e.getMessage());
        }
    }

    /**
     * 用户上传论文/软著/专利的证明材料
     *
     * @param applicationId
     * @param file
     * @param topic
     * @param awardTime
     * @return
     */
    @Override
    public ResponseResult<?> PaperEvidence(Integer applicationId, MultipartFile file, String topic, LocalDateTime awardTime) {
        LambdaQueryWrapper<Paper> wrapper1 = Wrappers.lambdaQuery(Paper.class)
                .eq(Paper::getId, applicationId);
        Paper paper1 = paperSubmitMapper.selectOne(wrapper1);
        String Uid = StpUtil.getLoginId().toString();
        if(paper1.getStatus() != APPROVED && paper1.getStatus() != SUBMITTED_RECOGNITION_REQUEST && paper1.getStatus() != REJECTED_RECOGNITION_REQUEST){
            return ResponseResult.Forbidden("你想干嘛啊？");
        }
        else if(!Uid.equals(paper1.getUid())){
            return ResponseResult.Forbidden("我求你了，我就一臭打工的，别整我了");
        }


        try {
            LambdaQueryWrapper<Student> wrapper2 = Wrappers.lambdaQuery(Student.class).eq(Student::getUid, Uid);
            Student student = studentMapper.selectOne(wrapper2);

            String title = paper1.getTitle();
            // 获取登录学生的学号
            String extensionName =  file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") );
            String objectName = "(" + student.getStudentClass() + student.getStudentName() + ")" + "_" + applicationId + "_" + title + extensionName;
            String path = Uid + "/" + MINIO_PAPER_EVIDENCE_PATH; // 假设这里定义了一个新的路径常量

            // 查询数据库中已有的文件记录
            LambdaQueryWrapper<Paper> wrapper = Wrappers.lambdaQuery(Paper.class)
                    .eq(Paper::getId, applicationId);
            Paper oldEvidence = paperSubmitMapper.selectOne(wrapper);

            if (oldEvidence != null) {
                // 检查 certificate 列是否有值
                if (oldEvidence.getCertificate() != null && !oldEvidence.getCertificate().isEmpty()) {
                    // 删除旧文件
                    //String bucketPath = oldEvidence.getCertificate();
                    //System.out.println(bucketPath);
                    // 删除旧文件
                    String oldObjectName = oldEvidence.getCertificate().substring(oldEvidence.getCertificate().lastIndexOf("/") + 1);

                    // 确保路径是从桶根目录开始的
                    String bucketPath = Uid + "/" + MINIO_PAPER_EVIDENCE_PATH + "/" + oldObjectName;
                    System.out.println(bucketPath);
                    boolean deleteSuccess = minioUtils.deleteFile(bucketName, bucketPath);
                    if (!deleteSuccess) {
                        return ResponseResult.InternalServerError("Minio删除旧文件失败");
                    }

                    // 更新现有记录
                    oldEvidence.setCertificate(null); // 清空旧文件URL
                }
            }


            // 上传文件到 Minio
            boolean uploadSuccess = minioUtils.uploadFile(file, bucketName, path, objectName);
            if (!uploadSuccess) {
                return ResponseResult.InternalServerError("Minio文件上传失败");
            }

            // 生成文件的完整路径
            String fileUrl = "http://" + ip + ":" + port + "/" + bucketName + "/" + path + "/" + objectName;

            // 更新新的 PaperEvidence 对象
            oldEvidence.setCertificate(fileUrl);
            oldEvidence.setTopic(topic);
            oldEvidence.setStatus(SUBMITTED_RECOGNITION_REQUEST);
            oldEvidence.setSubmitTime(LocalDateTime.now());
            oldEvidence.setAwardTime(awardTime);

            if (!(paperSubmitMapper.updateById(oldEvidence) > 0)) {
                throw new RuntimeException("更新申请状态失败");
            }

            return ResponseResult.success("文件上传成功");
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.InternalServerError("未知错误：" + e.getMessage());
        }
    }

    /**
     * 管理员批量认定论文级别
     * @param paperIdDTO
     * @param level
     * @return
     */
    @Override
    public ResponseResult<?> PaperDetermine(List<Integer> paperIdDTO, String isPass, Integer level) {
        try{
            String value =  "(" + String.join(", ", paperIdDTO.stream().map(String::valueOf).toArray(String[]::new)) + ")";
            String Uid = StpUtil.getLoginId().toString();
            for (Paper paper : paperSubmitMapper.selectBatchIds(paperIdDTO)) {
                LambdaQueryWrapper<Paper> wrapper = Wrappers.lambdaQuery(Paper.class)
                        .eq(Paper::getId, paper.getId());
                Paper paper1 = paperSubmitMapper.selectOne(wrapper);
                if (paper1.getStatus() != SUBMITTED_RECOGNITION_REQUEST) {
                    return ResponseResult.Unauthorized("存在错误状态申请");
                }
            }
            if (isPass.equals("false")) {

                int rowsUpdated = paperSubmitMapper.batchUpdateStatus(value,REJECTED_RECOGNITION_REQUEST);
                int rowsUpdated2 = paperSubmitMapper.batchUpdateCertificate(value);
                if (rowsUpdated <= 0 || rowsUpdated2 <= 0) {
                    throw new RuntimeException("批量更新失败");
                }
                return ResponseResult.success("批量更新成功");
            }
            else if(isPass.equals("true")){
                int rowsUpdated = paperSubmitMapper.batchUpdateFinalLevel(value, level.toString());
                int rowsUpdated1 = paperSubmitMapper.batchUpdateStatus(value,APPROVED_RECOGNITION_REQUEST);
                if (rowsUpdated <= 0 || rowsUpdated1 <= 0) {
                    throw new RuntimeException("批量更新失败");
                }
                return ResponseResult.success("批量更新成功");
            }
            else{
                return ResponseResult.Forbidden("你有权限吗，还是说你打错字了？");
            }
        }
        catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.BadRequest("未知错误：" + e.getMessage());
        }
    }


    @Override
    public void PaperExport(@RequestBody PaperSearchDTO paperSearchDTO, HttpServletResponse response) throws IOException {
        if (paperSearchDTO.getEndTime() != null && !paperSearchDTO.getEndTime().isEmpty()) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            paperSearchDTO.setEndTime(LocalDateTime.parse(paperSearchDTO.getEndTime(), formatter).plusDays(1).format(formatter));
        }

        System.out.println(paperSearchDTO.getStartTime());
        System.out.println(paperSearchDTO.getEndTime());

        // 获取数据
        List<Paper> lists = paperSubmitMapper.getCombinedApplicationData(
                paperSearchDTO.getStatus(),
                paperSearchDTO.getType(),
                paperSearchDTO.getFinalLevel(),
                paperSearchDTO.getStuName(),
                paperSearchDTO.getStartTime(),
                paperSearchDTO.getEndTime(),
                paperSearchDTO.getStuClass()
        );

        // 转换为新的DTO
        List<PaperDTOForExcel> excelLists = lists.stream()
                .map(PaperDTOMapper::mapToExcelDTO)
                .collect(Collectors.toList());

        // 按照指定的顺序排序，并处理可能的 null 值
        List<PaperDTOForExcel> sortedLists = excelLists.stream()
                .sorted(Comparator.comparing(PaperDTOForExcel::getCreateTime, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getFinalLevel, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getTitle, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getTopic, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getSubmitTime, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getAwardTime, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getCertificate, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getPermissionTime, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getStatus, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getTeamRank, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getParticipantMembers, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getUid, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getStudentClass, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getStudentName, Comparator.nullsFirst(Comparator.naturalOrder()))
                        .thenComparing(PaperDTOForExcel::getId, Comparator.nullsFirst(Comparator.naturalOrder())))
                .collect(Collectors.toList());

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            ExcelExportUtil.exportToExcel(sortedLists, baos);
            baos.flush();
        } catch (IOException e) {
            throw new RuntimeException("Failed to export Excel file", e);
        }

        byte[] bytes = baos.toByteArray();
        InputStream is = new ByteArrayInputStream(bytes);

        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment; filename=papers.xlsx");
        response.setContentLength(bytes.length);

        OutputStream os = response.getOutputStream();
        int len;
        byte[] buffer = new byte[1024];
        while ((len = is.read(buffer)) != -1) {
            os.write(buffer, 0, len);
        }
        is.close();
        os.close();
    }


}
